package com.jinjie.uitls;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.function.Function;

public class ConvertUtil {

    static Map<String, Function<Object, Object>> map = new HashMap<>();

    static {
        map.put("java.util.Date to java.lang.Long", o -> new Function<Object, Object>() {
            @Override
            public Object apply(Object o) {
                //do something to convert
                return ((Date)o).getTime();
            }
        });

    }

    /**
     * bean 转换
     * @param source
     * @param targetClazz
     * @return
     * @param <T>
     * @param <K>
     */
    public static <T, K> T convert(K source, Class<T> targetClazz) {
        T target;
        try {
            target = targetClazz.newInstance();
            Class<?> sourceClazz = source.getClass();
            Field[] sourceClassFields = getAllFields(sourceClazz);
            Field[] targetClassFields = getAllFields(targetClazz);

            for (Field sourceField : sourceClassFields) {
                sourceField.setAccessible(true);
                for (Field targetField : targetClassFields) {
                    if (targetField.getName().equals(sourceField.getName())) {
                        Object value = sourceField.get(source);
                        if (targetField.getType() != sourceField.getType()) {
                            value = mapValue(sourceField.getType(), targetField.getType(), value);
                        }

                        int mod = targetField.getModifiers();
                        if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
                            continue;
                        }
                        targetField.setAccessible(true);
                        targetField.set(target, value);
                        break;
                    }
                }
            }

        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e.getMessage());
        }
        return target;
    }

    /**
     * 获取 类型
     * @param cls
     * @return
     */
    public static Field[] getAllFields(final Class<?> cls) {
        final List<Field> allFieldsList = getAllFieldsList(cls);
        return allFieldsList.toArray(new Field[0]);
    }


    public static List<Field> getAllFieldsList(final Class<?> cls) {
        final List<Field> allFields = new ArrayList<Field>();
        Class<?> currentClass = cls;
        while (currentClass != null) {
            final Field[] declaredFields = currentClass.getDeclaredFields();
            allFields.addAll(Arrays.asList(declaredFields));
            currentClass = currentClass.getSuperclass();
        }
        return allFields;
    }

    public static Object mapValue(Class<?> sourceType, Class<?> targetType, Object sourceValue) {
        Function<Object, Object> function = map.get(sourceType.getName() + " to " + targetType.getName());
        if (function != null) {
            return function.apply(sourceValue);
        }
        return null;
    }

}
